package com.util;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

import android.util.Log;



public class HexUtil {
	public static DesMacUtil desmac=new DesMacUtil();
	public static IDEAUtil idea = new IDEAUtil();
	/**
	 * 用于建立十六进制字符的输出的小写字符数组
	 */
	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * 用于建立十六进制字符的输出的大写字符数组
	 */
	private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	/**
	 * 将字节数组转换为十六进制字符数组
	 *
	 * @param data
	 *            byte[]
	 * @return 十六进制char[]
	 */
	public static char[] encodeHex(byte[] data) {
		return encodeHex(data, true);
	}

	/**
	 * 将字节数组转换为十六进制字符数组
	 *
	 * @param data
	 *            byte[]
	 * @param toLowerCase
	 *            <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
	 * @return 十六进制char[]
	 */
	public static char[] encodeHex(byte[] data, boolean toLowerCase) {
		return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}

	/**
	 * 将字节数组转换为十六进制字符数组
	 *
	 * @param data
	 *            byte[]
	 * @param toDigits
	 *            用于控制输出的char[]
	 * @return 十六进制char[]
	 */
	protected static char[] encodeHex(byte[] data, char[] toDigits) {
		int l = data.length;
		char[] out = new char[l << 1];
		// two characters form the hex value.
		for (int i = 0, j = 0; i < l; i++) {
			out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
			out[j++] = toDigits[0x0F & data[i]];
		}
		return out;
	}
	public static String HexStringMemset(int nLen,int dec)
	{
		int i;
		StringBuilder strResult = new StringBuilder();
		strResult.append("");
		for(i=0;i<nLen;i++)
		{
			strResult.append(String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4]));
			strResult.append(String.valueOf(DIGITS_UPPER[dec&0x0F]));
		}
		return strResult.toString();
	}
	/**
	 * 将字节数组转换为十六进制字符串
	 *
	 * @param data
	 *            byte[]
	 * @return 十六进制String
	 */
	public static String encodeHexStr(byte[] data) {
		return encodeHexStr(data, true);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 *
	 * @param data
	 *            byte[]
	 * @param toLowerCase
	 *            <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
	 * @return 十六进制String
	 */
	public static String encodeHexStr(byte[] data, boolean toLowerCase) {
		return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 *
	 * @param data
	 *            byte[]
	 * @param toDigits
	 *            用于控制输出的char[]
	 * @return 十六进制String
	 */
	protected static String encodeHexStr(byte[] data, char[] toDigits) {
		return new String(encodeHex(data, toDigits));
	}

	/**
	 * 将十六进制字符数组转换为字节数组
	 *
	 * @param data
	 *            十六进制char[]
	 * @return byte[]
	 * @throws RuntimeException
	 *             如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
	 */
	public static byte[] decodeHex(char[] data) {

		int len = data.length;

		if ((len & 0x01) != 0) {
			throw new RuntimeException("Odd number of characters.");
		}

		byte[] out = new byte[len >> 1];

		// two characters form the hex value.
		for (int i = 0, j = 0; j < len; i++) {
			int f = toDigit(data[j], j) << 4;
			j++;
			f = f | toDigit(data[j], j);
			j++;
			out[i] = (byte) (f & 0xFF);
		}

		return out;
	}
	// char转byte
	private byte[] getBytes (char[] chars)
	{
		Charset cs = Charset.forName ("UTF-8");
		CharBuffer cb = CharBuffer.allocate (chars.length);
		cb.put (chars);
		cb.flip ();
		ByteBuffer bb = cs.encode (cb);

		return bb.array();
	}
	// byte转char
	private char[] getChars (byte[] bytes)
	{
		Charset cs = Charset.forName ("UTF-8");
		ByteBuffer bb = ByteBuffer.allocate (bytes.length);
		bb.put (bytes);
		bb.flip ();
		CharBuffer cb = cs.decode (bb);

		return cb.array();
	}
	/**
	 * 将Hex字符串转换成ASCI字符串
	 * @param strHex
	 * @return
	 * @throws Exception
	 */
//    public static String HexToAsciSting(String strHex)throws Exception
//    {
//    	byte [] bytes = StringToBytes(strHex);
//    	String strAsci=new String(bytes,"GBK");
//    	return strAsci;
//    }

//    public static String HexToAsciiString(String strHex){
//    	byte [] bytes = StringToBytes(strHex);
//    	String strAsci = "";
//		try {
//			strAsci = new String(bytes,"GBK");
//		} catch (UnsupportedEncodingException e) {
//			strAsci = "";
//		}
//    	return strAsci;
//    }
	public static String HexToAsciiString(String strHex){
		byte [] bytes = StringToBytes(strHex);
		int i=0;
		for( i =0;i<bytes.length;i++)
		{
			if(bytes[i]==0)
				break;
		}
		String strAsci = "";
		try {
			strAsci = new String(bytes,0,i,"GBK");
		} catch (UnsupportedEncodingException e) {
			strAsci = "";
		}
		return strAsci;
	}
	/**
	 * 将一个ASCI字符串转成HEX字符串
	 * @param strAsci
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String AsciToHexString(String strAsci) throws UnsupportedEncodingException
	{
		String s = String.valueOf(strAsci);
		byte[] bytes = s.getBytes("GBK");//e4baac413132333435000000
//		for (int i = 0; i < bytes.length; i++)
//			strHex += Integer.toHexString(bytes[i] & 0xff);
//		strHex.toLowerCase();
		return HexToString(bytes);
	}
	/**
	 * 将一个ASCI字符串转成HEX字符串,限定长度
	 * @param strAsci
	 * @param nLen长度限定,不足的补字符0
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String AsciToHexString(String strAsci,int nLen) throws UnsupportedEncodingException
	{
		String s = String.valueOf(strAsci);
		byte[] bytes = s.getBytes("GBK");//e4baac413132333435000000
		String strResult = HexToString(bytes);
		int strLen = strResult.length();
		if( strLen >= nLen )
			strResult = strResult.substring(0, nLen);
		else
		{
			int nAddLen = nLen - strLen;
			for(int i=0;i<nAddLen;i++)
				strResult+="0";
		}

		return strResult;
	}
	public static String HexToString(byte[]inHex)
	{
		byte i;
		StringBuilder strResult = new StringBuilder();
		strResult.append("");
		for(i=0;i<inHex.length;i++)
		{
			strResult.append(String.valueOf(DIGITS_UPPER[(0xF0 & inHex[i]) >>> 4]));
			strResult.append(String.valueOf(DIGITS_UPPER[inHex[i]&0x0F]));
		}
		return strResult.toString();
	}
	public static String BytesToString(byte[]inHex,int nOff,int nLen)
	{
		int i;
		StringBuilder strResult = new StringBuilder();
		strResult.append("");
		for(i=0;i<nLen;i++)
		{
			strResult.append(String.valueOf(DIGITS_UPPER[(0xF0 & inHex[nOff+i]) >>> 4]));
			strResult.append(String.valueOf(DIGITS_UPPER[inHex[nOff+i]&0x0F]));
		}
		return strResult.toString();
	}
	// 十进制转化为十六进制，结果为C8。
	//Integer.toHexString(200);
	/**
	 * 1字节转成2个字符串十六进制字符串
	 * @param dec
	 * @return
	 */
	public static String ByteToString(byte dec)
	{
		return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])+String.valueOf(DIGITS_UPPER[dec&0x0F]);
	}
	public static String ByteToString(int dec)
	{
		return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])+String.valueOf(DIGITS_UPPER[dec&0x0F]);
	}

	// 十六进制转化为十进制，结果140。
	//Integer.parseInt("8C",16);
	/**
	 * 2个字符十六进制字符串转成byte
	 * @param str
	 * @return
	 */
	public static byte StringToByte(String str)
	{
		return (byte)Integer.parseInt(str,16);
	}
	public static byte[] LongToHex( long inLong,int nLen,int flagOb)
	{
		int i=0;
		byte[] outHex = new byte[nLen];
		for(i=0;i<nLen;i++)
		{
			if(flagOb!=0)
				outHex[nLen-1-i]= (byte )(inLong>>(8*(nLen-1-i)));
			else
				outHex[i]= (byte )(inLong>>(8*(nLen-1-i)));
		}
		return outHex;

	}
	/**
	 * 整数转成十六进制格式字符串
	 */
	public static String LongToHexString( long inLong,int nLen,int flagOb )
	{
		return HexToString(LongToHex(inLong,nLen,flagOb));
	}
	/**
	 * 十六进制格式字符串转成整数
	 * @param hexstr 最多8个字符
	 * @return
	 */
	public static long HexStringToLong(String hexstr)
	{
		int nlen = hexstr.length()/2;
		long lResult=0;
		long lTmp;
		byte byteTmp;
		for(int i=0;i<nlen;i++)
		{
			byteTmp = StringToByte(hexstr.substring(i*2, (i+1)*2));
			lTmp = 	(byteTmp & 0xFF)<<(nlen-i-1)*8;
			lResult += lTmp;
		}
		return lResult;
	}
	/**
	 * 整形字符串转成十六进制字符串
	 * @param str
	 * @param nLimitLen 转换后字符的长度,必须是2的整数倍
	 * @return
	 */
	public static String IntStringToHexString(String str,int nLimitLen)
	{
		int nValue = Integer.parseInt(str);
		int nLen = nLimitLen/2;
		byte[] hexs = LongToHex(nValue,nLen,0);
		String strResult = HexToString(hexs);
		return strResult;
	}
	/**
	 * 将字符串转成byte[]
	 * @param str
	 * @return
	 */
	public static byte[] StringToBytes(String str)
	{
		int nLen = str.length();
		byte bytes[] = new byte[str.length()/2];
		for(int i=0;i<nLen/2;i++)
		{
			bytes[i] = StringToByte(str.substring(i*2, i*2+2));
		}
		return bytes;
	}
	/**
	 * 将字符串补80后转成byte[]
	 * @param str
	 * @return
	 */
	public static byte[] StringToBytes80(String str,int flagMac)
	{
		String str80 = str;
		int nLen = str.length();
		int add80Len = 8;

		if((nLen/2%8)!=0) add80Len = 8 - (nLen/2%8);
		if(flagMac==0)
		{
			if((add80Len==8)) add80Len = 0;
		}

		for(int i=0;i<add80Len;i++)
		{
			if( i == 0 ) str80+="80";
			else str80+="00";
		}
		nLen = str80.length()/2;
		byte bytes[] = new byte[nLen];
		for(int i=0;i<nLen;i++)
		{
			bytes[i] = StringToByte(str80.substring(i*2, i*2+2));
		}
		return bytes;
	}
	public static byte[] StringToBytes80(String str,int flagMac,int mult)
	{
		String str80 = str;
		int nLen = str.length();
		int add80Len = mult;

		if((nLen/2%mult)!=0) add80Len = mult - (nLen/2%mult);
		if(flagMac==0)
		{
			if((add80Len==mult)) add80Len = 0;
		}

		for(int i=0;i<add80Len;i++)
		{
			if( i == 0 ) str80+="80";
			else str80+="00";
		}
		nLen = str80.length()/2;
		byte bytes[] = new byte[nLen];
		for(int i=0;i<nLen;i++)
		{
			bytes[i] = StringToByte(str80.substring(i*2, i*2+2));
		}
		return bytes;
	}
	public static String StringApp80(String str,int flagMac)
	{
		String str80 = str;
		int nLen = str.length();
		int add80Len = 8;
		if((nLen/2%8)!=0) add80Len = 8 - (nLen/2%8);
		if(flagMac==0)
		{
			if((add80Len==8)) add80Len = 0;
		}
		for(int i=0;i<add80Len;i++)
		{
			if( i == 0 ) str80+="80";
			else str80+="00";
		}
		return str80;
	}
	public static String StringApp80(String str,int flagMac,int nMult)
	{
		String str80 = str;
		int nLen = str.length();
		int add80Len = nMult;
		if((nLen/2%nMult)!=0) add80Len = nMult - (nLen/2%nMult);
		if(flagMac==0)
		{
			if((add80Len==nMult)) add80Len = 0;
		}
		for(int i=0;i<add80Len;i++)
		{
			if( i == 0 ) str80+="80";
			else str80+="00";
		}
		return str80;
	}
	/**
	 * 计算3DESMAC
	 * @param Rand
	 * @param Key
	 * @param Value
	 * @return
	 */
	public static String CalDesMac(String Rand,String Key,String Value)
	{
		String strMac=new String();
		strMac = "";
		byte[] byteRand;
		byteRand = StringToBytes(Rand.substring(0,16));
		byte[] byteKey;
		byteKey = StringToBytes(Key.substring(0, 32));
		byte[] byteValue;
		byteValue = StringToBytes80(Value,1);
		byte[] bytesResult;
		bytesResult = desmac.CalDesMac(byteRand, byteKey, byteValue);
		strMac = HexToString(bytesResult);
		return strMac;
	}
	/**
	 * IDEA加密数据
	 * @param Key
	 * @param Value
	 * @return
	 */
	public static String EncodingIdea(String Key,String Value)
	{
		String strResult=new String();
		strResult = "";
		String strApp80 = StringApp80(Value,1);
		for(int i=0;i<(strApp80.length()/16);i++)
			strResult += idea.encodingCode(Key, strApp80.substring(i*16, (i+1)*16));
		return strResult;
	}
	public static String Encoding3Des(String Key,String Value)
	{
		String strResult=new String();
		strResult = "";
		byte[] byteKey;
		byteKey = StringToBytes(Key.substring(0, 32));
		byte[] byteValue;
		byteValue = StringToBytes80(Value,0);
		byte[] bytesResult;
		bytesResult = desmac.En3Des(byteKey, byteValue);
		strResult = HexToString(bytesResult);
		return strResult;
	}
	/**
	 * 生成指纹码
	 * @param Rand
	 * @param SessionKey
	 * @param Value
	 * @return
	 */
	public static String CalFingerprintKey(String Rand,String SessionKey,String Value)
	{
		Log.i("test",Value);
		//String Result = HexUtil.EncodingIdea(SessionKey, Value);
		String Result = HexUtil.Encoding3Des(SessionKey, Value);
		Log.i("计算IDEA:",Result);
		String macResult = HexUtil.CalDesMac(Rand, SessionKey.substring(8, 40), Result);
		Log.i("计算MAC:",macResult);
		return macResult;
	}
	public static String CalCrc(String Value)
	{
		char usIniCrc = 0x5075;
		char usResult;

		byte[] byteValue;
		byteValue = StringToBytes(Value);

		usResult = desmac.GetCrc(usIniCrc, byteValue);
		String strResult = HexToString(LongToHex(usResult, 2, 0));
		return strResult;
	}
	/**
	 * 产生字节随机数
	 * @param numByte 字节个数
	 * @return
	 */
	public static String GetRand(int numByte){
		//(int)(Math.Random()*n)
		String strRandom=new String();
		strRandom = "";
		for(byte i=0;i<numByte;i++)
			strRandom += ByteToString((byte)((int)(Math.random()*255)));
		return strRandom;
	}


	/**
	 * 将十六进制字符转换成一个整数
	 *
	 * @param ch
	 *            十六进制char
	 * @param index
	 *            十六进制字符在字符数组中的位置
	 * @return 一个整数
	 * @throws RuntimeException
	 *             当ch不是一个合法的十六进制字符时，抛出运行时异常
	 */
	protected static int toDigit(char ch, int index) {
		int digit = Character.digit(ch, 16);
		if (digit == -1) {
			throw new RuntimeException("Illegal hexadecimal character " + ch
					+ " at index " + index);
		}
		return digit;
	}

	public static void f_buff_xor(byte[] buf1,int nOffset1,byte[] buf2,int nOffset2,int i_len)
	{
		int i;
		for(i=0;i<i_len;i++)
		{
			buf1[nOffset1+i]= (byte) (buf1[nOffset1+i] ^ buf2[nOffset2+i]);
		}
	}
	private static SMS4 sms4 = new SMS4();
	public static String EnCrypteSm4(String Key,String Value)
	{
		String strResult=new String();
		strResult = "";
		byte[] byteKey;
		byteKey = StringToBytes(Key.substring(0, 32));
		byte[] byteValue;
		byteValue = StringToBytes80(Value,0,16);
		byte[] bytesResult = new byte[byteValue.length];
		sms4.sms4(byteValue, byteValue.length, byteKey, bytesResult,1);
		strResult = HexToString(bytesResult);
		return strResult;
	}
	public static String DeliveryKeysSM4(String Key,String Factor)
	{
		String strResult=new String();
		strResult = "";
		byte[] byteKey;
		byteKey = StringToBytes(Key.substring(0, 32));
		byte[] byteFactor;
		byteFactor = StringToBytes(Factor);
		byte[] bytesResult = new byte[16];
		sms4.Sm4DeliveryKeys(byteKey, byteFactor, bytesResult, byteFactor.length/8);
		strResult = HexToString(bytesResult);
		return strResult;
	}
	/**
	 * SM4线路保护写
	 * @param Key
	 * @param strRandom
	 * @param Value
	 * @return
	 */
	public static String GetMacSm4(String Key,String strRandom,String Value)
	{
		String strResult=new String();
		strResult = "";
		byte[] byteKey;
		byteKey = StringToBytes(Key.substring(0, 32));
		byte[] byteRandom;
		byteRandom = StringToBytes(strRandom.substring(0, 32));
		byte[] byteValue;
		byteValue = StringToBytes80(Value,1,16);
		byte[] bytesResult = new byte[byteValue.length];
		byte[] bytesProcess = new byte[16];
		for(int i=0;i<byteValue.length/16;i++)
		{
			if(i==0)
			{
				System.arraycopy(byteRandom, 0, bytesProcess, 0, 16);
			}
			f_buff_xor(bytesProcess,0,byteValue,i*16,16);
			sms4.sms4(bytesProcess, 16, byteKey, bytesResult,1);
			System.arraycopy(bytesResult, 0, bytesProcess, 0, 16);
		}
		strResult = BytesToString(bytesResult, 0, 4);

		return strResult;
	}
	public static void main(String[] args) {
		String srcStr = "待转换字符串";
		String encodeStr = encodeHexStr(srcStr.getBytes());
		String decodeStr = new String(decodeHex(encodeStr.toCharArray()));
		System.out.println("转换前：" + srcStr);
		System.out.println("转换后：" + encodeStr);
		System.out.println("还原后：" + decodeStr);
	}

	public String strHello;
	public String hello(String str) {
		String strTmp=new String();
		strTmp = strHello + str;
		return strTmp;
	}

	public void hello2(String str) {
		strHello = str;
	}
}
